{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 设计基函数(basis function) 以及数据读取"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def identity_basis(x):\n",
    "    ret = np.expand_dims(x, axis=1)\n",
    "    return ret\n",
    "\n",
    "def multinomial_basis(x, feature_num=10):\n",
    "    x = np.expand_dims(x, axis=1) # shape(N, 1)\n",
    "    feat = [x]\n",
    "    for i in range(2, feature_num+1):\n",
    "        feat.append(x**i)\n",
    "    ret = np.concatenate(feat, axis=1)\n",
    "    return ret\n",
    "\n",
    "def gaussian_basis(x, feature_num=20):\n",
    "    centers = np.linspace(0, 25, feature_num)\n",
    "    width = 1.0 * (centers[1] - centers[0])\n",
    "    x = np.expand_dims(x, axis=1)\n",
    "    x = np.concatenate([x]*feature_num, axis=1)\n",
    "    \n",
    "    out = (x-centers)/width\n",
    "    ret = np.exp(-0.5 * out ** 2)\n",
    "    return ret\n",
    "\n",
    "def load_data(filename, basis_func=gaussian_basis):\n",
    "    \"\"\"载入数据。\"\"\"\n",
    "    xys = []\n",
    "    with open(filename, 'r') as f:\n",
    "        for line in f:\n",
    "            xys.append(map(float, line.strip().split()))\n",
    "        xs, ys = zip(*xys)\n",
    "        xs, ys = np.asarray(xs), np.asarray(ys)\n",
    "        \n",
    "        o_x, o_y = xs, ys\n",
    "        phi0 = np.expand_dims(np.ones_like(xs), axis=1)\n",
    "        phi1 = basis_func(xs)\n",
    "        xs = np.concatenate([phi0, phi1], axis=1)\n",
    "        return (np.float32(xs), np.float32(ys)), (o_x, o_y) # [N, k], [N], [N], [N]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras import optimizers, layers, Model\n",
    "\n",
    "class linearModel(Model):\n",
    "    def __init__(self, ndim):\n",
    "        super(linearModel, self).__init__()\n",
    "        self.w = tf.Variable(\n",
    "            shape=[ndim, 1], \n",
    "            initial_value=tf.random.uniform(\n",
    "                [ndim,1], minval=-0.1, maxval=0.1, dtype=tf.float32))\n",
    "        \n",
    "    @tf.function\n",
    "    def call(self, x):\n",
    "        y = tf.squeeze(tf.matmul(x, self.w), axis=1)\n",
    "        return y\n",
    "\n",
    "(xs, ys), (o_x, o_y) = load_data('train.txt')        \n",
    "ndim = xs.shape[1]\n",
    "\n",
    "model = linearModel(ndim=ndim)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练以及评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "optimizer = optimizers.Adam(0.1)\n",
    "\n",
    "@tf.function\n",
    "def train_one_step(model, xs, ys):\n",
    "    with tf.GradientTape() as tape:\n",
    "        y_preds = model(xs)\n",
    "        loss = tf.reduce_mean(tf.sqrt(1e-12+(ys-y_preds)**2))\n",
    "    grads = tape.gradient(loss, model.w)\n",
    "    optimizer.apply_gradients([(grads, model.w)])\n",
    "    return loss\n",
    "\n",
    "@tf.function\n",
    "def predict(model, xs):\n",
    "    y_preds = model(xs)\n",
    "    return y_preds\n",
    "\n",
    "def evaluate(ys, ys_pred):\n",
    "    \"\"\"评估模型。\"\"\"\n",
    "    std = np.sqrt(np.mean(np.abs(ys - ys_pred) ** 2))\n",
    "    return std"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss is 11.71\n",
      "loss is 0.3149\n",
      "loss is 0.1388\n",
      "loss is 0.09928\n",
      "loss is 0.09873\n",
      "loss is 0.06879\n",
      "loss is 0.05686\n",
      "loss is 0.05294\n",
      "loss is 0.04872\n",
      "loss is 0.04732\n",
      "训练集预测值与真实值的标准差：0.1\n",
      "训练集预测值与真实值的标准差：0.2\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "for i in range(1000):\n",
    "    loss = train_one_step(model, xs, ys)\n",
    "    if i % 100 == 1:\n",
    "        print(f'loss is {loss:.4}')\n",
    "        \n",
    "        \n",
    "y_preds = predict(model, xs)\n",
    "std = evaluate(ys, y_preds)\n",
    "print('训练集预测值与真实值的标准差：{:.1f}'.format(std))\n",
    "\n",
    "(xs_test, ys_test), (o_x_test, o_y_test) = load_data('test.txt')\n",
    "\n",
    "y_test_preds = predict(model, xs_test)\n",
    "std = evaluate(ys_test, y_test_preds)\n",
    "print('训练集预测值与真实值的标准差：{:.1f}'.format(std))\n",
    "\n",
    "plt.plot(o_x, o_y, 'ro', markersize=3)\n",
    "plt.plot(o_x_test, y_test_preds, 'k')\n",
    "plt.xlabel('x')\n",
    "plt.ylabel('y')\n",
    "plt.title('Linear Regression')\n",
    "plt.legend(['train', 'test', 'pred'])\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
